-module(cluster_mgr).
-behaviour(gen_server).
-define(SERVER, ?MODULE).

-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
    case node() of
        'nonode@nohost' -> ignore;
        Node ->
            erlang:set_cookie(Node, cfg:get(cookie, "www.com.cn")),
            do_ping_nodes(Node),
            do_start_apps(Node)
    end,
    {ok, []}.

handle_call(_Request, _From, State) ->
    {reply, ok, State}.

handle_cast(_Request, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================
do_ping_nodes(Node) ->
    NodesOpts = cfg:get(nodes, []),
    PingNodes = lists:filtermap(fun({SNode, Opts})->
        IPStr = proplists:get_value(ip, Opts),
        NodeStr = utl:to_atom(utl:to_list(SNode) ++ "@" ++ IPStr),
        case NodeStr =:= Node of
            true -> false;
            false -> {true, NodeStr}
        end
    end, NodesOpts),
    do_ping_nodes1(PingNodes).

do_ping_nodes1([]) -> ok;
do_ping_nodes1([PingNode|T]) ->
    case net_adm:ping(PingNode) of
        pong-> 
            log:info("node ~p pong~n", [PingNode]),
            do_ping_nodes1(T);
        pang-> 
            timer:sleep(timer:seconds(1)),
            do_ping_nodes1(T ++ [PingNode])
    end.

do_start_apps(Node) ->
    SNode = ou:get_node_sname(Node),
    NodesOpts = cfg:get(nodes, []),
    case proplists:get_value(SNode, NodesOpts, undefined) of
        undefined -> ok;
        Opts ->
            Apps = proplists:get_value(apps, Opts),
            do_start_apps1(Apps)
    end.

do_start_apps1([]) -> ok;
do_start_apps1([App|T]) ->
    case application:ensure_started(App) of
        ok  ->
            do_start_apps1(T);
        _ ->
            log:info("start app ~p false~n", [App]),
            do_start_apps1([App|T])
    end.